热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开锁|载荷_基于STM32+华为云IOT设计的智能防盗单车锁

篇首语:本文由编程笔记#小编为大家整理,主要介绍了基于STM32+华为云IOT设计的智能防盗单车锁相关的知识,希望对你有一定的参考价值。一、前言

篇首语:本文由编程笔记#小编为大家整理,主要介绍了基于STM32+华为云IOT设计的智能防盗单车锁相关的知识,希望对你有一定的参考价值。



一、前言

近年来随着国民经济的发展,交通拥堵和环境污染问题越来越突出,而自行车对改善交通与环境起到了重要作用。中国本身是一个自行车使用大国,随着自行车的发展,自行车的科技含量越来越高,然而自行车安防问题突出。目前市场上自行车锁大多是传统机械结构车锁,没有实现智能化,急需解决。本文提出一种基于STM32单片机的智能自行车锁(马蹄锁)的设计方法,来提高自行车锁的智能化及安防等级。

硬件选项说明:单片机采用STM32F103RCT6,GSM模块采用SIM800C,完成网络连接、数据上传,GPS经纬度解析,短信发送,物联网平台采用华为云IOT,作为数据存储端,蓝牙模块采用正点原子低功耗BLE蓝牙,支持蓝牙开锁解锁,车辆的状态使用ADXL345三轴加速度传感器检测,密码键盘采用电容矩阵键盘。





二、设计思路总结

需要设计一款android手机APP,可以远程开锁解锁,手机APP对接华为云物联网平台,实现远程与自行车锁完成数据交互,命令下发。智能锁与华为云IOT服务器之间的通信协议采用MQTT协议,手机APP与华为云IOT服务器之间采用HTTP协议。智能锁除了支持远程开锁关锁之外,还支持蓝牙解锁和输入密码开始,设计的APP支持蓝牙功能,可以连接智能锁上的蓝牙完成开锁和关锁,如果没有带手机,可以输入密码完成开锁。

车辆的状态检测通过ADXL345三轴加速度计检测,如果车辆处于锁定状态,发现车辆被移动了会触发报警,锁里的蜂鸣器会持续响,并且SIM800C会向指定的手机号码发送短信,提示车辆可能被盗,同时上传GPS经纬度到云端服务器,手机APP上可以获取智能锁上传的GPS经纬度,调用百度地图显示车辆的位置,方便寻车。


三、硬件选型


(1) 加速度计传感器

ADXL345是一款小尺寸、薄型、低功耗、完整的三轴加速度计,提供经过信号调理的电压输出。

说明:CS接高电平则选择IIC通信,反之则SPI通信。SDO(地址引脚)接高电平,根据手册器件的7位I2C地址是0x1D,后面跟上读取/写位(R/W),则写寄存器为0x3A,读寄存器为0x3B;接低电平,则7位I2C地址是0x53,同理,跟上读写标志位后写寄存器为0xA6,读寄存器为0xA7;


(2) STM32开发板

STM32F103RCT6的芯体规格是32位,速度是72MHz,程序存储器容量是256KB,程序存储器类型是FLASH,RAM容量是48K。


(3) BLE低功耗蓝牙模块


(4) SIM800C

模块特点:

1、支持极限DC5V-18V宽电压输入

2、有电源使能开关引脚EN

3、支持锂电池供电接口VBAT3.5-4.5V

4、输入支持移动和联通手机卡Micro SIM卡

5、送51/STM32/ARDUINO驱动例程

1、DC 5V-18V电源输入,推荐使用DC 9V

2、电源开始使能引脚默认使能

3、电源地

4、GSM模块的TXD引脚接其它模块的RXD

5、GSM模块的RXD引脚接其它模块的TXD

6、数据终端准备

7、内核音频输出引脚

8、内核音频输出引脚

9、锂电池输入引脚,DC 3.5 - 4.5V

10、电源地

11、启动引脚和GND短路可实现开机自启动

12、电源地

13、RTC外置电池引脚

14、内核振铃提示引脚

15、内合音频输入引脚

16、内核音频输入引脚

加粗的引脚一般都用到。

建议使用V_IN单独供电DC5-18V输入(推荐使用9V),或者VBAT供电锂电池两种供电方式这两种供电方式最稳定。如果只是简单调试,也可使用USB-TTL或者开发板的5V直接给模块供电。不过一般电脑或者开发板的功率有限,可能会不稳定。请根据具体情况自己取舍选择合适电源。


3. 手机APP软件设计


3.1 通信说明

上位机与设备之间支持通过BLE低功耗串口蓝牙进行通信,支持通过网络连接华为云服务器进行通信,手机APP下发open_lock和close_lock实现关锁开锁。


3.2 搭建开发环境

上位机软件采用Qt框架设计,Qt是一个跨平台的C++图形用户界面应用程序框架。Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。简单来说,QT可以很轻松的帮你做带界面的软件,甚至不需要你投入很大精力。

QT官网: https://www.qt.io/

QT学习入门实战专栏文章: https://blog.csdn.net/xiaolong1126626497/category_11400392.html

QT5.12.6的下载地址:
https://download.qt.io/archive/qt/5.12/5.12.6/


4. 创建云端设备


4.1 创建产品

登录官网: https://www.huaweicloud.com/product/iothub.html

直接搜索物联网,打开页面。




4.2 自定义模型







4.3 注册设备




设备创建成功:


"device_id": "6274b1d62d5e854503d3a67e_lock",
"secret": "12345678"


4.4 MQTT设备密匙

创建完产品、设备之后,接下来就需要知道如何通过MQTT协议登陆华为云服务器。
官方的详细介绍在这里:
https://support.huaweicloud.com/devg-iothub/iot_01_2127.html#ZH-CN_TOPIC_0240834853__zh-cn_topic_0251997880_li365284516112

属性上报格式:
https://support.huaweicloud.com/api-iothub/iot_06_v5_3010.html

MQTT设备登陆密匙生成地址:

DeviceId 6274b1d62d5e854503d3a67e_lock
DeviceSecret 12345678
ClientId 6274b1d62d5e854503d3a67e_lock_0_0_2022050605
Username 6274b1d62d5e854503d3a67e_lock
Password 334dd7c0c10e47280880e9dd004ae0d8c5abc24dbbc9daa735315722707fe13b

4.5 使用MQTT客户端软件登录

所有的参数已经得到,接下来采用MQTT客户端登录华为云进行测试。
华为云物联网平台的域名是: 161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
华为云物联网平台的IP地址是:121.36.42.100
在软件里参数填充正确之后,就看到设备已经连接成功了。
接下来打开设备页面,可以看到设备已经在线了。


4.6 数据上报测试

//订阅主题: 平台下发消息给设备
$oc/devices/6274b1d62d5e854503d3a67e_lock/sys/messages/down
//设备上报数据
$oc/devices/6274b1d62d5e854503d3a67e_lock/sys/properties/report
//上报的属性消息 (一次可以上报多个属性,在json里增加就行了)
"services": ["service_id": "lock","properties":"lock":1]



//订阅主题: 平台下发消息给设备
$oc/devices/6274b1d62d5e854503d3a67e_lock/sys/messages/down
//设备上报数据
$oc/devices/6274b1d62d5e854503d3a67e_lock/sys/properties/report
//上报的属性消息 (一次可以上报多个属性,在json里增加就行了)
"services": ["service_id": "lock","properties":"GPS信息":"lat:12.345,lng:45.678"]

4.7 应用侧开发

为了更方便的展示设备数据,与设备完成交互,还需要开发一个配套的上位机,官方提供了应用侧开发的API接口、SDK接口,为了方便通用一点,我这里采用了API接口完成数据交互,上位机软件采用QT开发。

帮助文档地址: ttps://support.huaweicloud.com/api-iothub/iot_06_v5_0034.html

设备属性就是设备上传的传感器状态数据信息,应用侧提供了API接口,可以主动向设备端下发请求指令;设备端收到指令之后需要按照约定的数据格式上报数据;所以,要实现应用层与设备端的数据交互,需要应用层与设备端配合才能完成。



5. STM32开发

STM32连接华为云IOT的工程代码Get: https://download.csdn.net/download/xiaolong1126626497/81993720


5.1 ADXL345.c

#include "app.h"
/*
函数功能: 各种硬初始化
继电器模块--DAT--->PA4
PB12-----输入引脚,检测模块是否连接或者断开
*/

void Hardware_Init(void)

RCC->APB2ENR|&#61;1<<2;
GPIOA->CRL&&#61;0xFFF0FFFF;
GPIOA->CRL|&#61;0x00030000;

RCC->APB2ENR|&#61;1<<3;
GPIOB->CRH&&#61;0xFFF0FFFF;
GPIOB->CRH|&#61;0x00080000;

//
//初始化ADXL345.
//返回值:0,初始化成功;1,初始化失败.
u8 ADXL345_Init(void)

IIC_Init(); //初始化IIC总线
if(ADXL345_RD_Reg(DEVICE_ID)&#61;&#61;0XE5) //读取器件ID

ADXL345_WR_Reg(DATA_FORMAT,0X2B); //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
ADXL345_WR_Reg(BW_RATE,0x0A); //数据输出速度为100Hz
ADXL345_WR_Reg(POWER_CTL,0x28); //链接使能,测量模式
ADXL345_WR_Reg(INT_ENABLE,0x00); //不使用中断
ADXL345_WR_Reg(OFSX,0x00);
ADXL345_WR_Reg(OFSY,0x00);
ADXL345_WR_Reg(OFSZ,0x00);
return 0;

return 1;

//写ADXL345寄存器
//addr:寄存器地址
//val:要写入的值
//返回值:无
void ADXL345_WR_Reg(u8 addr,u8 val)

IIC_Start();
IIC_Send_Byte(ADXL_WRITE); //发送写器件指令
IIC_Wait_Ack();
IIC_Send_Byte(addr); //发送寄存器地址
IIC_Wait_Ack();
IIC_Send_Byte(val); //发送值
IIC_Wait_Ack();
IIC_Stop(); //产生一个停止条件

//读ADXL345寄存器
//addr:寄存器地址
//返回值:读到的值
u8 ADXL345_RD_Reg(u8 addr)

u8 temp&#61;0;
IIC_Start();
IIC_Send_Byte(ADXL_WRITE); //发送写器件指令
temp&#61;IIC_Wait_Ack();
IIC_Send_Byte(addr); //发送寄存器地址
temp&#61;IIC_Wait_Ack();
IIC_Start(); //重新启动
IIC_Send_Byte(ADXL_READ); //发送读器件指令
temp&#61;IIC_Wait_Ack();
temp&#61;IIC_Read_Byte(0); //读取一个字节,不继续再读,发送NAK
IIC_Stop(); //产生一个停止条件
return temp; //返回读到的值

//读取ADXL的平均值
//x,y,z:读取10次后取平均值
void ADXL345_RD_Avval(short *x,short *y,short *z)

short tx&#61;0,ty&#61;0,tz&#61;0;
u8 i;
for(i&#61;0;i<10;i&#43;&#43;)

ADXL345_RD_XYZ(x,y,z);
delay_ms(10);
tx&#43;&#61;(short)*x;
ty&#43;&#61;(short)*y;
tz&#43;&#61;(short)*z;

*x&#61;tx/10;
*y&#61;ty/10;
*z&#61;tz/10;

//自动校准
//xval,yval,zval:x,y,z轴的校准值
void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval)

short tx,ty,tz;
u8 i;
short offx&#61;0,offy&#61;0,offz&#61;0;
ADXL345_WR_Reg(POWER_CTL,0x00); //先进入休眠模式.
delay_ms(100);
ADXL345_WR_Reg(DATA_FORMAT,0X2B); //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
ADXL345_WR_Reg(BW_RATE,0x0A); //数据输出速度为100Hz
ADXL345_WR_Reg(POWER_CTL,0x28); //链接使能,测量模式
ADXL345_WR_Reg(INT_ENABLE,0x00); //不使用中断
ADXL345_WR_Reg(OFSX,0x00);
ADXL345_WR_Reg(OFSY,0x00);
ADXL345_WR_Reg(OFSZ,0x00);
delay_ms(12);
for(i&#61;0;i<10;i&#43;&#43;)

ADXL345_RD_Avval(&tx,&ty,&tz);
offx&#43;&#61;tx;
offy&#43;&#61;ty;
offz&#43;&#61;tz;

offx/&#61;10;
offy/&#61;10;
offz/&#61;10;
*xval&#61;-offx/4;
*yval&#61;-offy/4;
*zval&#61;-(offz-256)/4;
ADXL345_WR_Reg(OFSX,*xval);
ADXL345_WR_Reg(OFSY,*yval);
ADXL345_WR_Reg(OFSZ,*zval);

//读取3个轴的数据
//x,y,z:读取到的数据
void ADXL345_RD_XYZ(short *x,short *y,short *z)

u8 buf[6];
u8 i;
IIC_Start();
IIC_Send_Byte(ADXL_WRITE); //发送写器件指令
IIC_Wait_Ack();
IIC_Send_Byte(0x32); //发送寄存器地址(数据缓存的起始地址为0X32)
IIC_Wait_Ack();

IIC_Start(); //重新启动
IIC_Send_Byte(ADXL_READ); //发送读器件指令
IIC_Wait_Ack();
for(i&#61;0;i<6;i&#43;&#43;)

if(i&#61;&#61;5)buf[i]&#61;IIC_Read_Byte(0);//读取一个字节,不继续再读,发送NACK
else buf[i]&#61;IIC_Read_Byte(1); //读取一个字节,继续读,发送ACK

IIC_Stop(); //产生一个停止条件
*x&#61;(short)(((u16)buf[1]<<8)&#43;buf[0]);
*y&#61;(short)(((u16)buf[3]<<8)&#43;buf[2]);
*z&#61;(short)(((u16)buf[5]<<8)&#43;buf[4]);

//读取ADXL345的数据times次,再取平均
//x,y,z:读到的数据
//times:读取多少次
void ADXL345_Read_Average(short *x,short *y,short *z,u8 times)

u8 i;
short tx,ty,tz;
*x&#61;0;
*y&#61;0;
*z&#61;0;
if(times)//读取次数不为0

for(i&#61;0;i<times;i&#43;&#43;)//连续读取times次

ADXL345_RD_XYZ(&tx,&ty,&tz);
*x&#43;&#61;tx;
*y&#43;&#61;ty;
*z&#43;&#61;tz;
delay_ms(5);

*x/&#61;times;
*y/&#61;times;
*z/&#61;times;


//得到角度
//x,y,z:x,y,z方向的重力加速度分量(不需要单位,直接数值即可)
//dir:要获得的角度.0,与Z轴的角度;1,与X轴的角度;2,与Y轴的角度.
//返回值:角度值.单位0.1°.
short ADXL345_Get_Angle(float x,float y,float z,u8 dir)

float temp;
float res&#61;0;
switch(dir)

case 0://与自然Z轴的角度
temp&#61;sqrt((x*x&#43;y*y))/z;
res&#61;atan(temp);
break;
case 1://与自然X轴的角度
temp&#61;x/sqrt((y*y&#43;z*z));
res&#61;atan(temp);
break;
case 2://与自然Y轴的角度
temp&#61;y/sqrt((x*x&#43;z*z));
res&#61;atan(temp);
break;

return res*1800/3.14;

//初始化IIC
void IIC_Init(void)

RCC->APB2ENR|&#61;1<<3; //先使能外设IO PORTB时钟
GPIOB->CRL&&#61;0X00FFFFFF; //6/7 推挽输出
GPIOB->CRL|&#61;0X33000000;
GPIOB->ODR|&#61;3<<6; //6,7 输出高

//产生IIC起始信号
void IIC_Start(void)

SDA_OUT(); //sda线输出
IIC_SDA&#61;1;
IIC_SCL&#61;1;
delay_us(4);
IIC_SDA&#61;0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL&#61;0;//钳住I2C总线&#xff0c;准备发送或接收数据

//产生IIC停止信号
void IIC_Stop(void)

SDA_OUT();//sda线输出
IIC_SCL&#61;0;
IIC_SDA&#61;0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL&#61;1;
IIC_SDA&#61;1;//发送I2C总线结束信号
delay_us(4);

//等待应答信号到来
//返回值&#xff1a;1&#xff0c;接收应答失败
// 0&#xff0c;接收应答成功
u8 IIC_Wait_Ack(void)

u8 ucErrTime&#61;0;
SDA_IN(); //SDA设置为输入
IIC_SDA&#61;1;delay_us(1);
IIC_SCL&#61;1;delay_us(1);
while(READ_SDA)

ucErrTime&#43;&#43;;
if(ucErrTime>250)

IIC_Stop();
return 1;


IIC_SCL&#61;0;//时钟输出0
return 0;

//产生ACK应答
void IIC_Ack(void)

IIC_SCL&#61;0;
SDA_OUT();
IIC_SDA&#61;0;
delay_us(2);
IIC_SCL&#61;1;
delay_us(2);
IIC_SCL&#61;0;

//不产生ACK应答
void IIC_NAck(void)

IIC_SCL&#61;0;
SDA_OUT();
IIC_SDA&#61;1;
delay_us(2);
IIC_SCL&#61;1;
delay_us(2);
IIC_SCL&#61;0;

//IIC发送一个字节
//返回从机有无应答
//1&#xff0c;有应答
//0&#xff0c;无应答
void IIC_Send_Byte(u8 txd)

u8 t;
SDA_OUT();
IIC_SCL&#61;0;//拉低时钟开始数据传输
for(t&#61;0;t<8;t&#43;&#43;)

IIC_SDA&#61;(txd&0x80)>>7;
txd<<&#61;1 var cpro_id = "u6885494";

推荐阅读
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
  • 移动端常用单位——rem的使用方法和注意事项
    本文介绍了移动端常用的单位rem的使用方法和注意事项,包括px、%、em、vw、vh等其他常用单位的比较。同时还介绍了如何通过JS获取视口宽度并动态调整rem的值,以适应不同设备的屏幕大小。此外,还提到了rem目前在移动端的主流地位。 ... [详细]
  • centos安装Mysql的方法及步骤详解
    本文介绍了centos安装Mysql的两种方式:rpm方式和绿色方式安装,详细介绍了安装所需的软件包以及安装过程中的注意事项,包括检查是否安装成功的方法。通过本文,读者可以了解到在centos系统上如何正确安装Mysql。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • MACElasticsearch安装步骤及验证方法
    本文介绍了MACElasticsearch的安装步骤,包括下载ZIP文件、解压到安装目录、启动服务,并提供了验证启动是否成功的方法。同时,还介绍了安装elasticsearch-head插件的方法,以便于进行查询操作。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
author-avatar
灰色头像6888
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有